This notebook mirrors mesh.stats.html
In [1]:
from pathlib import Path
from ipyniivue import download_dataset
BASE_API_URL = "https://niivue.com/demos/images/"
DATA_FOLDER = Path("images")
# Download data for example
download_dataset(
BASE_API_URL,
DATA_FOLDER,
files=[
"BrainMesh_ICBM152.lh.curv",
"BrainMesh_ICBM152.lh.motor.mz3",
"BrainMesh_ICBM152.lh.mz3",
],
)
BrainMesh_ICBM152.lh.curv already exists. BrainMesh_ICBM152.lh.motor.mz3 already exists. BrainMesh_ICBM152.lh.mz3 already exists. Dataset downloaded successfully to images.
In [2]:
import ipywidgets as widgets
from ipyniivue import ColormapType, Mesh, MeshLayer, NiiVue, SliceType
# 1. Initialize NiiVue
nv = NiiVue()
nv.opts.is_colorbar = True
nv.opts.back_color = (0.3, 0.3, 0.3, 1.0)
nv.opts.show_3d_crosshair = True
nv.opts.slice_type = SliceType.RENDER
# 2. Define Layers
# Layer 0: Curvature (Gray)
layer0 = MeshLayer(
path=DATA_FOLDER / "BrainMesh_ICBM152.lh.curv",
colormap="gray",
cal_min=0.3,
cal_max=0.5,
opacity=0.7,
)
layer0.colorbar_visible = False # notice how this is not added in kwargs
# Layer 1: Motor Map (Warm/Winter)
layer1 = MeshLayer(
path=DATA_FOLDER / "BrainMesh_ICBM152.lh.motor.mz3",
cal_min=1.5,
cal_max=5.0,
colormap="warm",
colormap_negative="winter",
use_negative_cmap=True,
opacity=0.7,
)
# 3. Load Mesh with Layers
mesh = Mesh(
path=DATA_FOLDER / "BrainMesh_ICBM152.lh.mz3",
layers=[layer0, layer1],
rgba255=[255, 255, 255, 255],
)
nv.meshes = [mesh]
# 4. Define Widgets & Interactions
# --- Sliders ---
# Curvature Opacity (Layer 0)
curve_slider = widgets.FloatSlider(
value=0.7, min=0, max=1.0, step=0.1, description="Curvature"
)
def on_curve_change(change):
"""Handle curve change."""
layer0.opacity = change["new"]
curve_slider.observe(on_curve_change, names="value")
# Threshold & Range (Layer 1 cal_min/cal_max)
thresh_slider = widgets.FloatSlider(
value=1.5, min=0.1, max=10.0, step=0.1, description="Threshold"
)
range_slider = widgets.FloatSlider(
value=3.5, min=0.1, max=9.0, step=0.1, description="Range"
)
def update_thresh_range(_):
"""Update thresh range."""
mn = thresh_slider.value
mx = mn + range_slider.value
layer1.cal_min = mn
layer1.cal_max = mx
thresh_slider.observe(update_thresh_range, names="value")
range_slider.observe(update_thresh_range, names="value")
# Opacity (Layer 1)
opacity_slider = widgets.FloatSlider(
value=0.7, min=0, max=1.0, step=0.1, description="Opacity"
)
def on_opacity_change(change):
"""Handle opacity change."""
layer1.opacity = change["new"]
opacity_slider.observe(on_opacity_change, names="value")
# --- Checkboxes ---
# Negative Colors
negative_check = widgets.Checkbox(value=True, description="NegativeColors")
def on_negative_change(change):
"""Handle negative change."""
layer1.use_negative_cmap = change["new"]
nv.refresh_colormaps()
negative_check.observe(on_negative_change, names="value")
# Diverging Colors
diverge_check = widgets.Checkbox(value=False, description="Diverging Colors")
def on_diverge_change(change):
"""Handle diverge change."""
if change["new"]:
layer1.colormap = "green2orange"
layer1.colormap_negative = "green2cyan"
else:
layer1.colormap = "warm"
layer1.colormap_negative = "winter"
diverge_check.observe(on_diverge_change, names="value")
# Dark Background
dark_check = widgets.Checkbox(value=True, description="Dark")
def on_dark_change(change):
"""Handle background change."""
v = 0.3 if change["new"] else 1.0
nv.opts.back_color = (v, v, v, 1.0)
dark_check.observe(on_dark_change, names="value")
# --- Dropdowns ---
# Colormap Type
cmap_type_drop = widgets.Dropdown(
options=[
("restrict colorbar to range", ColormapType.MIN_TO_MAX.value),
(
"colorbar from 0, transparent sub",
ColormapType.ZERO_TO_MAX_TRANSPARENT_BELOW_MIN.value,
),
(
"colorbar from 0, translucent sub",
ColormapType.ZERO_TO_MAX_TRANSLUCENT_BELOW_MIN.value,
),
],
value=ColormapType.MIN_TO_MAX.value,
description="Cmap Type",
)
def on_cmap_type_change(change):
"""Handle cmap type change."""
layer1.colormap_type = ColormapType(change["new"])
cmap_type_drop.observe(on_cmap_type_change, names="value")
# Outline Border
outline_drop = widgets.Dropdown(
options=[("no outline", 0), ("opaque outline", 1), ("black outline", -1)],
value=0,
description="Outline",
)
def on_outline_change(change):
"""Handle outline change."""
layer1.outline_border = float(change["new"])
outline_drop.observe(on_outline_change, names="value")
# Mesh Base Color
color_drop = widgets.Dropdown(
options=["white", "red", "green", "blue"], value="white", description="Color"
)
def on_color_change(change):
"""Handle color change."""
c = change["new"]
rgb = [255, 255, 255]
if c == "red":
rgb = [255, 32, 32]
elif c == "green":
rgb = [0, 222, 32]
elif c == "blue":
rgb = [92, 128, 255]
mesh.rgba255 = [*rgb, 255] # Add alpha
color_drop.observe(on_color_change, names="value")
# Mesh Shaders
shader_names = nv.mesh_shader_names()
shader_dropdown = widgets.Dropdown(
options=shader_names, value="Phong", description="Shader"
)
def on_shader_change(change):
"""Handle shader change."""
nv.set_mesh_shader(mesh.id, change["new"])
shader_dropdown.observe(on_shader_change, names="value")
# --- Layout ---
ui = widgets.VBox(
[
widgets.HBox([curve_slider, thresh_slider]),
widgets.HBox([range_slider, opacity_slider]),
widgets.HBox([negative_check, diverge_check, dark_check]),
widgets.HBox([cmap_type_drop, outline_drop]),
widgets.HBox([color_drop, shader_dropdown]),
nv,
]
)
# Display All
ui
Out[2]: